package net.goutalk.glcs.module.bi.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.DbUtil;
import cn.hutool.db.Entity;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.toolkit.MPJWrappers;
import net.goutalk.glcs.common.constant.GlobalConstant;
import net.goutalk.glcs.common.enums.MenuType;
import net.goutalk.glcs.common.enums.PublishStateType;
import net.goutalk.glcs.common.enums.YesOrNoEnum;
import net.goutalk.glcs.common.page.ConventPage;
import net.goutalk.glcs.common.page.PageOutput;
import net.goutalk.glcs.common.utils.DatasourceUtil;
import net.goutalk.glcs.common.utils.VoToColumnUtil;
import net.goutalk.glcs.module.bi.dto.CancelMenuDto;
import net.goutalk.glcs.module.bi.dto.ProjectPageDto;
import net.goutalk.glcs.module.bi.dto.PublishMenuDto;
import net.goutalk.glcs.module.bi.entity.Project;
import net.goutalk.glcs.module.bi.mapper.ProjectMapper;
import net.goutalk.glcs.module.bi.service.IProjectService;
import net.goutalk.glcs.module.bi.vo.ProjectPageVo;
import net.goutalk.glcs.module.system.entity.Menu;
import net.goutalk.glcs.module.system.mapper.MenuMapper;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.sql.DataSource;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 项目表 服务实现类
 * </p>
 *
 * @author tanyujie
 * @since 2022-11-06
 */
@Service
@AllArgsConstructor
public class ProjectServiceImpl extends MPJBaseServiceImpl<ProjectMapper, Project> implements IProjectService {

    private final static String PREVIEW_URL_PRE = "/#/chart/preview/";

    private final static String IFARME_STRING = "IFrame";
    private final MenuMapper menuMapper;

    @Override
    public PageOutput<ProjectPageVo> getPage(ProjectPageDto dto) {

        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StrUtil.isNotBlank(dto.getKeyword()), Project::getProjectName, dto.getKeyword())
                .select(Project.class, x -> VoToColumnUtil.fieldsToColumns(ProjectPageVo.class).contains(x.getProperty()));

        IPage<Project> page = page(ConventPage.getPage(dto), queryWrapper);
        PageOutput<ProjectPageVo> pageOutput = ConventPage.getPageOutput(page, ProjectPageVo.class);

        List<Long> allMenuId = pageOutput.getList().stream().map(ProjectPageVo::getMenuId).collect(Collectors.toList());

        List<Menu> menuList = menuMapper.selectJoinList(Menu.class,
                MPJWrappers.<Menu>lambdaJoin()
                        .disableLogicDel()
                        .in(ObjectUtils.isNotEmpty(allMenuId) && allMenuId.size() > 0, Menu::getId, allMenuId));

        for (ProjectPageVo projectPageVo : pageOutput.getList()) {
            Optional<Menu> menuOptional = menuList.stream().filter(x -> x.getId().equals(projectPageVo.getMenuId())).findFirst();

            //如果能查询到菜单数据  代表 要么 发布过  要么 正在发布
            if (menuOptional.isPresent()) {
                // 如果式已删除状态   属于  发布过已经取消状态
                if (menuOptional.get().getDeleteMark() == YesOrNoEnum.YES.getCode()) {
                    projectPageVo.setPublishState(PublishStateType.PT.getCode());
                } else {
                    projectPageVo.setPublishState(PublishStateType.ING.getCode());
                }

            } else {
                projectPageVo.setPublishState(PublishStateType.NO.getCode());
            }

        }
        return pageOutput;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    public boolean publishMenu(PublishMenuDto dto) {

        Menu menu = BeanUtil.toBean(dto, Menu.class);

        if (ObjectUtil.isEmpty(menu.getParentId())){
            menu.setParentId(0L);
        }
        if (ObjectUtil.isEmpty(menu.getSystemId())){
            menu.setSystemId(1L);
        }
        menu.setComponent(IFARME_STRING);
        menu.setComponentType(YesOrNoEnum.YES.getCode());
        menu.setPath(dto.getUrl() + PREVIEW_URL_PRE + dto.getProjectId());
        menu.setMenuType(MenuType.FUNCTION.getCode());
        menu.setDisplay(YesOrNoEnum.YES.getCode());
        menu.setAllowDelete(YesOrNoEnum.YES.getCode());
        menu.setAllowModify(YesOrNoEnum.YES.getCode());
        menu.setOutLink(YesOrNoEnum.YES.getCode());
        menu.setKeepAlive(YesOrNoEnum.NO.getCode());
        menu.setName(menu.getTitle());

        //如果没有传入 menuId  默认是新增  如果传入了 就是修改
        if (ObjectUtil.isNotNull(dto.getMenuId())) {
//            menu.setDeleteMark(YesOrNoEnum.NO.getCode());
            menuMapper.updateById(menu);

            String tableName = "glcs_menu";

            DataSource datasourceMaster = DatasourceUtil.getDatasourceMaster();
            Entity entity = Entity.create(tableName).set(GlobalConstant.DELETE_MARK, YesOrNoEnum.NO.getCode());
            Entity where = Entity.create(tableName).set(GlobalConstant.DEFAULT_PK, menu.getId());
            DbUtil.use(datasourceMaster).update(entity, where);
        } else {
            menuMapper.insert(menu);
        }

        Project project = new Project();
        project.setId(dto.getProjectId());
        project.setMenuId(menu.getId());

        updateById(project);

        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelMenu(CancelMenuDto dto) {

        Project project = new Project();
        project.setId(dto.getId());

        updateById(project);

        menuMapper.deleteById(dto.getMenuId());


        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteProject(List<Long> ids) {

        LambdaQueryWrapper<Project> select = Wrappers.lambdaQuery(Project.class).in(Project::getId, ids).isNotNull(Project::getMenuId).select(Project::getMenuId);
        List<Project> list = list(select);

        if (list.size() > 0) {
            List<Long> menuId = list.stream().map(Project::getMenuId).collect(Collectors.toList());

            menuMapper.deleteBatchIds(menuId);
        }


        removeByIds(ids);
        return Boolean.TRUE;
    }
}
